package com.fr.base.core.list;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.AbstractList;
import sun.misc.Cleaner;

public class MBBList extends AbstractList
{
  private File cacheFile = null;
  private MappedByteBuffer mapped_read;
  private MappedByteBuffer mapped_write;
  byte[] page;
  int pageSize = 3145727;
  int pageoffset = 0;
  private FileChannel fc;
  private int total_size;
  int[] size_array;
  int[] index_array;
  int count = 0;

  public MBBList(File paramFile, int paramInt)
  {
    this.page = new byte[this.pageSize];
    this.size_array = new int[paramInt];
    this.index_array = new int[paramInt + 1];
    this.cacheFile = paramFile;
  }

  public MBBList(File paramFile, int paramInt1, int paramInt2)
  {
    this.pageSize = paramInt2;
    this.page = new byte[this.pageSize];
    this.size_array = new int[paramInt1];
    this.index_array = new int[paramInt1 + 1];
    this.cacheFile = paramFile;
  }

  public static void un_map(MappedByteBuffer paramMappedByteBuffer)
  {
    if (paramMappedByteBuffer != null)
    {
      paramMappedByteBuffer.force();
      AccessController.doPrivileged(new PrivilegedAction(paramMappedByteBuffer)
      {
        private final MappedByteBuffer val$buffer;

        public Object run()
        {
          Method localMethod;
          try
          {
            localMethod = this.val$buffer.getClass().getMethod("cleaner", new Class[0]);
            localMethod.setAccessible(true);
            Cleaner localCleaner = (Cleaner)localMethod.invoke(this.val$buffer, new Object[0]);
            if (localCleaner != null)
            {
              localCleaner.clean();
              localCleaner.clear();
            }
          }
          catch (Exception localException)
          {
            localException.printStackTrace();
          }
          return null;
        }
      });
    }
  }

  public boolean add(Object paramObject)
  {
    ByteArrayOutputStream localByteArrayOutputStream;
    try
    {
      localByteArrayOutputStream = new ByteArrayOutputStream();
      ObjectOutputStream localObjectOutputStream = new ObjectOutputStream(localByteArrayOutputStream);
      localObjectOutputStream.writeObject(paramObject);
      byte[] arrayOfByte = localByteArrayOutputStream.toByteArray();
      if (this.pageoffset + arrayOfByte.length < this.pageSize)
      {
        i = 0;
        while (true)
        {
          if (i >= arrayOfByte.length)
            break label245;
          this.page[(this.pageoffset++)] = arrayOfByte[i];
          ++i;
        }
      }
      for (int i = 0; i < arrayOfByte.length; ++i)
      {
        this.page[(this.pageoffset++)] = arrayOfByte[i];
        if (this.pageoffset >= this.pageSize)
        {
          if (this.mapped_write != null)
          {
            this.mapped_write.clear();
            un_map(this.mapped_write);
            this.mapped_write = null;
          }
          getFileChannel();
          this.mapped_write = this.fc.map(FileChannel.MapMode.READ_WRITE, this.fc.size(), this.pageSize);
          this.mapped_write.put(this.page);
          this.pageoffset = 0;
          this.total_size += this.pageSize;
          if (this.mapped_read != null)
          {
            this.mapped_read.clear();
            un_map(this.mapped_read);
            this.mapped_read = null;
          }
        }
      }
      label245: this.size_array[this.count] = arrayOfByte.length;
      this.index_array[(this.count + 1)] = (this.index_array[this.count] + arrayOfByte.length);
      this.count += 1;
    }
    catch (Exception localException)
    {
      throw new RuntimeException(localException);
    }
    return true;
  }

  public Object get(int paramInt)
  {
    if (paramInt % 10000 == 0)
      System.out.println(paramInt);
    try
    {
      byte[] arrayOfByte = new byte[this.size_array[paramInt]];
      int i = this.index_array[paramInt] + this.size_array[paramInt];
      int j = 0;
      if (this.total_size == 0)
      {
        int k = this.index_array[paramInt];
        while (k < i)
        {
          arrayOfByte[j] = this.page[k];
          ++k;
          ++j;
        }
        ByteArrayInputStream localByteArrayInputStream1 = new ByteArrayInputStream(arrayOfByte);
        localObjectInputStream = new ObjectInputStream(localByteArrayInputStream1);
        return localObjectInputStream.readObject();
      }
      getFileChannel();
      if (this.mapped_read == null)
      {
        System.out.println("Current size is:" + this.total_size);
        this.mapped_read = this.fc.map(FileChannel.MapMode.READ_ONLY, 0L, this.total_size);
      }
      if (i < this.fc.size())
      {
        l = this.index_array[paramInt];
        while (true)
        {
          if (l >= i)
            break label359;
          arrayOfByte[j] = this.mapped_read.get(l);
          ++l;
          ++j;
        }
      }
      if ((i > this.total_size) && (this.index_array[paramInt] < this.total_size))
      {
        l = this.index_array[paramInt];
        while (l < this.fc.size())
        {
          arrayOfByte[j] = this.mapped_read.get(l);
          ++l;
          ++j;
        }
        l = this.total_size;
        while (true)
        {
          if (l >= i)
            break label359;
          arrayOfByte[j] = this.page[(l - this.total_size)];
          ++l;
          ++j;
        }
      }
      int l = this.index_array[paramInt];
      while (l < i)
      {
        arrayOfByte[j] = this.page[(l - this.total_size)];
        ++l;
        ++j;
      }
      label359: ByteArrayInputStream localByteArrayInputStream2 = new ByteArrayInputStream(arrayOfByte);
      ObjectInputStream localObjectInputStream = new ObjectInputStream(localByteArrayInputStream2);
      return localObjectInputStream.readObject();
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new RuntimeException(localClassNotFoundException);
    }
    catch (IOException localIOException)
    {
      throw new RuntimeException(localIOException);
    }
  }

  public int size()
  {
    return this.count;
  }

  public void clear()
  {
    this.size_array = null;
    if (this.mapped_read != null)
    {
      this.mapped_read.clear();
      un_map(this.mapped_read);
      this.mapped_read = null;
    }
    if (this.mapped_write != null)
    {
      this.mapped_write.clear();
      un_map(this.mapped_write);
      this.mapped_write = null;
    }
    this.pageoffset = 0;
    if (this.fc != null)
      try
      {
        this.fc.close();
        this.fc = null;
      }
      catch (IOException localIOException)
      {
        throw new RuntimeException(localIOException);
      }
    this.page = null;
  }

  private FileChannel getFileChannel()
  {
    if (this.fc == null)
      try
      {
        this.fc = new RandomAccessFile(this.cacheFile, "rw").getChannel();
      }
      catch (IOException localIOException)
      {
        throw new RuntimeException(localIOException);
      }
    return this.fc;
  }

  protected void finalize()
    throws Throwable
  {
    finalize();
    clear();
  }
}